﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using MimicAPI;
using MimicAPI.Window;
using swForms = System.Windows.Forms;

// TODO : Have a look on "\CodeProject\TrayMinimizer" for hot keys management

namespace Mimic
{
    /// <summary>Interaction logic for App.xaml</summary>
    public partial class App : Application
    {
        /// <summary>Name of the mutex used to check the unicity</summary>
        const string MutexName = "MutexMimic";
        /// <summary>Notify icon : it used System.Windows.Forms because there is no such control in WPF !</summary>
        swForms.NotifyIcon notifyIcon;

        void Application_Startup(object sender, StartupEventArgs e)
        {
            // Because we use a few the notifyIcon... This call is usefull to get the usual style :)
            swForms.Application.EnableVisualStyles();

            // Step 1 : Check the Version of the OS (Vista or better is required)
            if (Environment.OSVersion.Version.Major < 6)
            {
                // UNDONE : Manage a version without thumbnails ! (But that allows to minimize windows into the trail)
                MessageBox.Show("Mimic requires Windows Vista or better. Sorry !", "Unable to run on \"old\" systems", MessageBoxButton.OK, MessageBoxImage.Stop);
                Application.Current.Shutdown();
                return;
            }

            // Step 2 : Check the unicity
            bool createdNewMutex;
            Mutex mutex = new Mutex(true, MutexName, out createdNewMutex);
            if (!createdNewMutex)
            {
                mutex.Close();
                // There is a bug here when running in x64...
                try
                {
                    TaskDialog.Show("Only one instance is allowed", "Mimic is already running",
                                    "Well... Running several instances has no interest :)", TaskDialogButtons.Ok, TaskDialogIcon.Warning);
                }
                catch
                {
                    MessageBox.Show("Mimic is already running", "Only one instance is allowed", MessageBoxButton.OK, MessageBoxImage.Warning);
                }
                Application.Current.Shutdown();
                return;
            }

            // We keep our mutex alive till the end of the application !
            this.Exit += (src, args) => { GC.KeepAlive(mutex); notifyIcon.Visible = false; WindowExtensions.UnMinimizeAll(); };
            this.DispatcherUnhandledException += delegate(object src, DispatcherUnhandledExceptionEventArgs args)
                        {
                            // TODO : This task dialog should be removed in the final version
                            // (and replaced by an invitation to send the error by mail to mimic-bug@zorglonde.com)
                            TaskDialog.Show("Unhandled exception", args.Exception.Message, args.Exception.StackTrace,
                                            TaskDialogButtons.Ok, TaskDialogIcon.Error);
                            args.Handled = true;
                        };

            // Step 3 : we create the window list
            this.MainWindow = new MainWindow();
            this.MainWindow.Closing += MainWindow_Closing;

            // Step 4 : Configure and show a notification icon in the system tray
            notifyIcon = new swForms.NotifyIcon()
                        {
                            Icon = Icon.FromHandle(Mimic.Properties.Resources.application_cascade.GetHicon()),
                            Text = "Mimic",
                            ContextMenuStrip = new swForms.ContextMenuStrip(),
                            Visible = true,
                            BalloonTipIcon = swForms.ToolTipIcon.None,
                            BalloonTipTitle = "Mimic",
                            BalloonTipText = "is now running"
                        };
            notifyIcon.ContextMenuStrip.Items.AddRange(new swForms.ToolStripItem[]
                        {
                            new swForms.ToolStripMenuItem("Show windows list", Mimic.Properties.Resources.application_cascade, HideShowWindowsList, "HideShowMenuItem"),
                            new swForms.ToolStripSeparator(),
                            new swForms.ToolStripMenuItem("About", Mimic.Properties.Resources.information, ShowAboutBox),
                            new swForms.ToolStripMenuItem("Exit Mimic", Mimic.Properties.Resources.door_in, (src, args) => Application.Current.Shutdown())
                        });
            notifyIcon.DoubleClick += HideShowWindowsList;
            notifyIcon.ShowBalloonTip(1);
        }

        void MainWindow_Closing(object sender, CancelEventArgs evArgs)
        {
            // The main window should never be closed (otherwise it will close the whole application)

            // We cancel the closing
            evArgs.Cancel = true;
            // We want to hide the window.
            // There is a bug here : Cf. http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=549662&SiteID=1
            // Because of the bug, we cannot call directly Hide(), we must invoke async using Dispatcher.CurrentDispatcher.BeginInvoke
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(HideWindowsList));
        }

        void HideShowWindowsList(object snd, EventArgs args)
        {
            if (!(this.MainWindow is MainWindow))
            {
                // The main window seems not to exist... We recreate it
                this.MainWindow = new MainWindow();
                this.MainWindow.Closing += MainWindow_Closing;
            }
            if (this.MainWindow.IsVisible)
                HideWindowsList();
            else
            {
                ((MainWindow)this.MainWindow).RefreshWindowsList();
                this.MainWindow.Show();
                notifyIcon.ContextMenuStrip.Items["HideShowMenuItem"].Text = "Hide windows list";
            }
        }

        void HideWindowsList()
        {
            if (this.MainWindow != null)
                this.MainWindow.Hide();
            notifyIcon.ContextMenuStrip.Items["HideShowMenuItem"].Text = "Show windows list";
        }

        void ShowAboutBox(object snd, EventArgs args)
        {
            // TODO : To be improved with HTML links... + allow only one instance
            TaskDialog.Show(this.MainWindow, "About Mimic",
                            string.Format("Author : Gilles Péron{0}" +
                                          "Project : http://www.codeplex.org/Mimic", Environment.NewLine),
                            string.Format("Current version : {0}{1}" +
                                          "Mail : gilles.peron@gmail.com{1}" +
                                          "Web : http://www.zorglonde.com{1}{1}" +
                                          "Resources :{1}" +
                                          "  . Icons : Silk icon set 1.3 by Mark James{1}" +
                                          "            (http://www.famfamfam.com/lab/icons/silk/)",
                                          Assembly.GetExecutingAssembly().GetName().Version.ToString(), Environment.NewLine),
                            TaskDialogButtons.Ok, TaskDialogIcon.Information);
        }
    }
}
